<?php
namespace app\shop\library\order;

use cubox\Cubox;
use app\shop\library\Goods;
use app\shop\library\order\OrderItem;
use app\shop\library\Snowflake;
use app\shop\library\Lock;
use app\shop\library\order\item\freight;
use app\shop\library\order\item\goodsCoupon;
use app\shop\library\order\item\freightCoupon;

class Order{

    public $member_id;
    public $order_id;
    private $goodsList;
    private $detail = [];
    private $item = [];

    const STATUS_LIST = [
        'new'=>'新订单',
        'wait_pay'=>'待付款',
        'wait_delivery'=>'待发货',
        'wait_receive'=>'待收货',
        'complete'=>'已完成',
        'cancel'=>'已取消',
        'refund'=>'已退款',
    ];


    //TODO 暂时把订单项写死，后续的执行顺序和扩展看需求再优化
    const ORDER_ITEM = [
        freight::class,
        freightCoupon::class,
        goodsCoupon::class,
    ];

    public static function getStatusName($status){
        return self::STATUS_LIST[$status]??'未定义';
    }

    public function __construct(int $member_id,array $post)
    {
        if (!isset($post['goods'])){
            throw new \Exception('商品列表不能为空');
        }

        $goodsData = $this->getGoodsData($post['goods']);
        $total = 0;
        foreach ($goodsData as $key => $goodsItem){
            $total +=  $goodsItem['num'] * $goodsItem['price'];
            $goodsItem['total'] =  $total;
            $goodsItem['pay'] = $total;
            $this->goodsList[$goodsItem['goods_id']] =  $goodsItem;
           
        }

        $this->addDetail('total',$total);
        $this->member_id = $member_id;
        
        foreach (self::ORDER_ITEM as $itemClass){
            $this->addItem(new $itemClass($this->member_id,$post));
        }

        
    }


    public function addItem(OrderItem $item){
        $this->item[] = $item;
        $item->count($this);
    }

    public function addDetail($name,$money,$desc=''){
        $this->detail[$name] = [
            'money'=>$money,
            'desc'=>$desc
        ];
    }


    public function setGoodsDiscount($goods_id,$discount){
        $this->goodsList[$goods_id]['pay'] += abs($discount)*-1;            
    }
    public function total(){
        $pay = 0;
        foreach ($this->detail as $detailItem){
            $pay += $detailItem['money'];
        }
        return $pay;
    }

    public function list(){
        return $this->goodsList;
    }

    public function detail($name =''){
        if ($name != ''){
            return $this->detail[$name];
        }else{
            return $this->detail;
        }
    }


    public function save($mobile,$payment,$remark,array $address){
        $shop = Cubox::app('shop');
        Lock::acquire();
        $snowflake =  new Snowflake($shop->cache(),'order');
        $this->order_id  = $snowflake->nextId();

        if ($this->total() < 0){
            throw new \Exception('订单总价不能小于0');
        }

        

        //扣除库存
        if(!Stock::reduce($this->goodsList)){
            Lock::release();
            throw new \Exception('库存不足');
        }

        $orderGoods = $shop->model('OrderGoods');
        $order = $shop->model('Order'); 

        $db = $shop->db();
        $db->beginTransaction();

        $goods_num = 0;
        foreach ($this->goodsList as $goodsItem){
            $itemData = [];
            $itemData['goods_id'] = $goodsItem['goods_id'];
            $itemData['order_id'] = $this->order_id;
            $itemData['num'] = $goodsItem['num'];
            $itemData['title'] = $goodsItem['title'];
            $itemData['price'] = $goodsItem['price'];
            $itemData['picture'] = $goodsItem['picture_main'];
            $itemData['sku_id'] = $goodsItem['sku_id'];
            $itemData['sku_name'] = $goodsItem['sku_name'];
            $itemData['money_total'] = $goodsItem['total'];
            $itemData['money_pay'] = $goodsItem['pay'];
            $goods_num += $goodsItem['num'];
            $orderGoods->insert($itemData);
        }

        $orderData = [
            'order_id' => $this->order_id,
            'member_id' => $this->member_id,
            'member_mobile'=>$mobile,
            'status' => 'new',
            'goods_num' =>  $goods_num,
            'remark' => $remark,
            'payment_way' => $payment,
            'address_city'=> $address['city'],
            'address_detail'=> $address['detail'],
            'address_contacts'=> $address['contacts'],
            'address_phone'=> $address['phone'],
            'money_total' => $this->detail['total']['money'],
            'money_freight' => $this->detail['freight']['money']??0,
            'money_pay' => $this->total(),
            'money_detail' => json_encode($this->detail()),
        ];
        
        $order->insert($orderData);
        
        foreach ($this->item as $item){
            $item->save($this);
        }

        try{
            $db->commit();
            Lock::release();
            return $this->order_id;
        }catch(\Exception $e){
            $db->rollback();
            Stock::recovery($this->goodsList); //库存回滚
            Lock::release();
            Cubox::log('shop-order:'.$this->order_id.' '.$e->getMessage());
            //项目回滚
            foreach ($this->item as $item) {
                $item->rollback($this);
            }

            return false;
        }

    }

    private function getGoodsData(array $goodsList):array{
        $data = [];

        //status off 下架的问题记得处理
       
        foreach($goodsList as $goodsItem){
            if (isset($goodsItem['goods_id']) && isset($goodsItem['num']) && $goodsItem['goods_id']!='' && $goodsItem['num']>0){
                $goods_id = $goodsItem['goods_id'];
                $arr = explode('_',$goods_id);
                $sku_id = '';
                if (count($arr)==2){
                    $goods_id = $arr[0];
                    $sku_id = $arr[1];
                }

                if ($goodsData = Goods::get($goods_id)){
                    $goodsData['num'] = $goodsItem['num'];
                    
                    if ($sku_id){
                        $sku = array_filter($goodsData['sku'],function($item)use($sku_id){
                            return $item['sku_id'] == $sku_id;
                        });

                        if (count($sku)>0){
                            $sku = array_shift($sku);
                            $goodsData['sku_id'] = $sku_id;
                            $goodsData['sku_name'] = $sku['name'];
                            $goodsData['price'] = $sku['price'];
                        }else{
                            throw new \Exception('商品规格不存在');
                        }
                    }else{
                        $goodsData['sku_id'] = '';
                        $goodsData['sku_name'] = '';
                    }


                    $data[] = $goodsData;
                }else{
                    throw new \Exception('商品不存在');
                }
            }else{
                throw new \Exception('商品数据错误');
            }
        }
        return $data;
    }
}
